﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using WMM.Tapioca.Taxonomy;
using System.IO;
using WMM.Tapioca;
using WMM.Tapioca.Formula;
using WMM.Tapioca.XbrlDimension;
using WMM.Tapioca.Linkbase;
using System.Xml.Schema;
using WMM.Tapioca.Formula.Filters;
using System.Text.RegularExpressions;

namespace TapiocaWpf.Model
{
    public class DiagramGraphs
    {
        static XbrlDocument xbrlDoc;

        public void CreateDotFile(string selectedNodeId, string linkbase, XbrlDocument xbrlDocument, ref string pathToDotFile)
        {
            xbrlDoc = xbrlDocument;

            DTS dts = xbrlDocument.Dts;

            if (File.Exists(linkbase + "Graph.dot"))
            {
                File.Delete(linkbase + "Graph.dot");
            }

            pathToDotFile = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "\\Tapioca\\" + linkbase + "Graph.dot";

            if (linkbase == "dimension")
            {
                CreateDimensionalDotFile(selectedNodeId, xbrlDocument, ref pathToDotFile);
                return;
            }

            StringBuilder content = new StringBuilder();

            content.AppendLine("digraph " + linkbase + "Graph {");
            content.AppendLine("graph [fontsize=10 fontname=\"Verdana\" compound=true];");
            content.AppendLine("node [shape=record fontsize=10 fontname=\"Verdana\"];");
            content.AppendLine("edge[color = blue];");
            content.AppendLine("concentrate = red;");

            int k = 0;

            foreach (NetworkGraph ng in xbrlDocument.Dts.NetworkGraphs)
            {
                if (ng.TupleNG.Item1.Equals(linkbase + "Link"))
                {
                    string definition = GetDefinitionOfRoleType(ng.TupleNG.Item2);

                    if (definition == selectedNodeId)
                    {
                        content.AppendLine("subgraph \"cluster_" + k + "\" {");
                        content.AppendLine("\tlabel = \"linkrole:" + ng.TupleNG.Item2 + "  arcrole:" + ng.TupleNG.Item4 + "\";");
                        content.AppendLine("\tstyle=\"filled;\"");
                        content.AppendLine("\tcolor=gray;");

                        foreach (Arc arc in ng.NetworkRelationships)
                        {
                            Locator locatorTo = dts.GetLocator(arc.ExtendedLinkParent.Locators, arc.ToId);
                            Concept conceptTo = dts.GetConceptByID(locatorTo.HrefResourceId);
                            Locator locatorFrom = dts.GetLocator(arc.ExtendedLinkParent.Locators, arc.FromId);
                            Concept conceptFrom = dts.GetConceptByID(locatorFrom.HrefResourceId);
                            
                            string arcRole = ng.TupleNG.Item4.Substring(ng.TupleNG.Item4.LastIndexOf('/') + 1);

                            content.AppendLine("\t\"" + ng.TupleNG.Item2 + ng.TupleNG.Item4 + conceptFrom.Name + "\" [label=\"" + conceptFrom.Name + "\"];");
                            content.AppendLine("\t\"" + ng.TupleNG.Item2 + ng.TupleNG.Item4 + conceptTo.Name + "\" [label=\"" + conceptTo.Name + "\"];");

                            string weight = "";

                            if (arc.Weight != 0)
                            {
                                weight = "\nweight=" + arc.Weight;
                            }

                            if (arc.Weight == -1)
                            {
                                content.AppendLine("\t\"" + ng.TupleNG.Item2 + ng.TupleNG.Item4 + conceptFrom.Name + "\" -> \"" + ng.TupleNG.Item2 + ng.TupleNG.Item4 + conceptTo.Name + "\" [fontsize=8 fontcolor = grey25 fontname=Verdana color=red,label=\"" + arcRole + weight + "\"];");
                            }
                            else
                            {
                                content.AppendLine("\t\"" + ng.TupleNG.Item2 + ng.TupleNG.Item4 + conceptFrom.Name + "\" -> \"" + ng.TupleNG.Item2 + ng.TupleNG.Item4 + conceptTo.Name + "\" [fontsize=8 fontcolor = grey25 fontname=Verdana,label=\"" + arcRole + weight + "\"];");
                            }
                        }

                        content.AppendLine("}");
                        content.AppendLine("");

                        k = k + 1;
                    }
                }
            }

            content.AppendLine("}");

            File.WriteAllText(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "\\Tapioca\\" + linkbase + "Graph.dot", content.ToString());
        }


        private static string GetDefinitionOfRoleType(string roleUri)
        {
            foreach (RoleType roleType in xbrlDoc.Dts.RoleTypes)
            {
                if (roleType.RoleUri.Equals(roleUri))
                {
                    if (roleType.Definition != null)
                    {
                        return roleType.Definition;
                    }
                    else
                    {
                        return roleUri;
                    }
                }
            }

            return roleUri;
        }


        public void CreateDimensionalDotFile(string selectedNodeId, XbrlDocument xbrlDoc, ref string pathToDotFile)
        {
            string fontColor = "grey";
            int k = 1;

            StringBuilder content = new StringBuilder();

            content.AppendLine("digraph " + "Dimensional" + "Graph {");
            content.AppendLine("graph [fontsize=10 fontname=\"Verdana\" compound=true];");
            content.AppendLine("node [shape=ellipse fontsize=10 fontname=\"Verdana\"];");
            content.AppendLine("edge[color = blue];");
            content.AppendLine("concentrate = red;");

            foreach (DimensionalRelationshipSet drs in xbrlDoc.Dts.DtsDimension.DimensionalRelationshipSets)
            {
                string role = drs.DRSRole;
                
                content.AppendLine("subgraph cluster_" + k + " {");
                content.AppendLine("\tlabel = \"" + drs.DRSRole + "\";");

                string definition = GetDefinitionOfRoleType(drs.DRSRole);

                if (definition == selectedNodeId)
                {
                    foreach (ConsecutiveRelationshipsSet crs in drs.ConsecutiveRelationshipsSets)
                    {
                        if (Path.GetFileName(crs.HasHypercube.Compositor) == "all")
                        {
                            content.AppendLine("\tedge[color = blue];");
                            fontColor = "black";
                        }
                        else
                        {
                            content.AppendLine("\tedge[color = red];");
                            fontColor = "red";
                        }

                        content.AppendLine("\tcolor=lightgrey;");

                        string sourceRoleHasHypercube = crs.HasHypercube.SourceRole;

                        // PrimaryItemsInherited

                        //DrawPrimaryItemsInherited(xbrlDoc, fontColor, content, crs.HasHypercube.LocatorPrimaryItem);

                        foreach (Inheritance inheritance in xbrlDoc.Dts.DtsDimension.Inheritances)
                        {
                            string EffectiveRoleInheritance = (inheritance.TargetRole != null ? inheritance.TargetRole.AbsoluteUri : inheritance.SourceRole);

                            foreach (Concept conceptInherited in inheritance.PrimaryItemsInherited)
                            {
                                if (inheritance.PrimaryItem.Id.Equals(crs.HasHypercube.PrimaryItem.Id) && inheritance.SourceRole.Equals(drs.DRSRole))
                                {
                                    content.AppendLine("\t\"" + conceptInherited.Name + EffectiveRoleInheritance + "\" [style = filled, fillcolor = gray, label=\"" + conceptInherited.Name + "\"];");
                                    content.AppendLine("\t\"" + conceptInherited.Name + EffectiveRoleInheritance + "\" -> \"" + crs.HasHypercube.Hypercube.Concept.Name + crs.HasHypercube.EffectiveRole + "\" [fontsize=8 fontcolor = " + fontColor + " fontname=Verdana,label=\"" + Path.GetFileName(crs.HasHypercube.Compositor) + (crs.HasHypercube.Closed ? "\nclosed" : "") + "\"];");
                                    //content.AppendLine("\t\"" + conceptInherited.Name + EffectiveRoleInheritance + "\" -> \"" + crs.HasHypercube.PrimaryItem.Name + sourceRoleHasHypercube + "\" [fontsize=8 fontcolor = " + fontColor + " fontname=Verdana,label=\"" + "domain-member" + "\"];");
                                }
                            }
                        }

                        content.AppendLine("\t\"" + crs.HasHypercube.PrimaryItem.Name + sourceRoleHasHypercube + "\" [style = filled, fillcolor = white, penwidth=2, label=\"" + crs.HasHypercube.PrimaryItem.Name + "\"];");
                        content.AppendLine("\t\"" + crs.HasHypercube.Hypercube.Concept.Name + crs.HasHypercube.EffectiveRole + "\" [shape=box3d, style = filled, fillcolor = aquamarine, label=\"" + crs.HasHypercube.Hypercube.Concept.Name + "\"];");
                        content.AppendLine("\t\"" + crs.HasHypercube.PrimaryItem.Name + sourceRoleHasHypercube + "\" -> \"" + crs.HasHypercube.Hypercube.Concept.Name + crs.HasHypercube.EffectiveRole + "\" [fontsize=8 fontcolor = " + fontColor + " fontname=Verdana,label=\"" + Path.GetFileName(crs.HasHypercube.Compositor) + (crs.HasHypercube.Closed ? "\nclosed" : "") + "\"];");

                        foreach (HypercubeDimension hypercubeDimension in crs.HypercubeDimensions)
                        {
                            string sourceRoleHypercubeDimension = hypercubeDimension.SourceRole;

                            content.AppendLine("\t\"" + hypercubeDimension.Dimension.Concept.Name + hypercubeDimension.EffectiveRole + "\" [label=\"" + hypercubeDimension.Dimension.Concept.Name + "\"];");
                            content.AppendLine("\t\"" + hypercubeDimension.Hypercube.Concept.Name + sourceRoleHypercubeDimension + "\" -> \"" + hypercubeDimension.Dimension.Concept.Name + hypercubeDimension.EffectiveRole + "\" [fontsize=8 fontcolor = " + fontColor + " fontname=Verdana,label=\"" + "hypercube-dimension" + "\"];");

                            // DimensionDefault
                            if (hypercubeDimension.Dimension.DefaultConcept != null)
                            {
                                content.AppendLine("\t\"" + hypercubeDimension.Dimension.DefaultConcept.Name + hypercubeDimension.Dimension.DefaultDimensionRole + "dimension-default" + "\" [label=\"" + hypercubeDimension.Dimension.DefaultConcept.Name.Replace(".", "") + "\"];");
                                content.AppendLine("\t\"" + hypercubeDimension.Dimension.Concept.Name + hypercubeDimension.EffectiveRole + "\" -> \"" + hypercubeDimension.Dimension.DefaultConcept.Name + hypercubeDimension.Dimension.DefaultDimensionRole + "dimension-default" + "\" [fontsize=8 fontcolor = red fontname=Verdana,label=\"" + "dimension-default" + "\"];");
                            }

                            foreach (DimensionDomain dimensionDomain in crs.DimensionDomains)
                            {
                                if (dimensionDomain.Dimension == hypercubeDimension.Dimension)
                                {
                                    string sourceRoleDimensionDomain = dimensionDomain.SourceRole;

                                    content.AppendLine("\t\"" + dimensionDomain.Domain.Concept.Name + dimensionDomain.EffectiveRole + "\" [label=\"" + dimensionDomain.Domain.Concept.Name + "\"];");
                                    content.AppendLine("\t\"" + dimensionDomain.Dimension.Concept.Name + sourceRoleDimensionDomain + "\" -> \"" + dimensionDomain.Domain.Concept.Name + dimensionDomain.EffectiveRole + "\" [fontsize=8 fontcolor = " + fontColor + " fontname=Verdana,label=\"" + "dimension-domain" + "\"];");

                                    foreach (DomainMember domainMember in crs.DomainMembers)
                                    {
                                        string sourceRoleDomainMember = domainMember.SourceRole;

                                        if (dimensionDomain.Domain.Concept.Name.Equals(domainMember.Domain.Name))
                                        {
                                            if (!domainMember.Usable)
                                            {
                                                content.AppendLine("\t\"" + domainMember.Member.Name + domainMember.EffectiveRole + "\" [label=\"" + domainMember.Member + "\"];");
                                                content.AppendLine("\t\"" + domainMember.Domain.Name + sourceRoleDomainMember + "\" -> \"" + domainMember.Member.Name + domainMember.EffectiveRole + " [fontsize=8  fontname=Verdana," +
                                                                    "label=<" +
                                                                    "<table cellpadding=\"0\" cellborder=\"0\" cellspacing=\"0\" border=\"0\">" +
                                                                    "<tr>" +
                                                                    "<td><font color=\"#0000FF\">domain-member</font></td>" +
                                                                    "</tr>" +
                                                                    "<tr>" +
                                                                    "<td><font color=\"#FF0000\">usable=false</font></td>" +
                                                                    "</tr>" +
                                                                    "</table>" +
                                                                    ">];");
                                            }
                                            else
                                            {
                                                content.AppendLine("\t\"" + domainMember.Member.Name + domainMember.EffectiveRole + "\" [label=\"" + domainMember.Member.Name + "\"];");
                                                content.AppendLine("\t\"" + domainMember.Domain.Name + sourceRoleDomainMember + "\" -> \"" + domainMember.Member.Name + domainMember.EffectiveRole + "\" [fontsize=8 fontcolor = " + fontColor + " fontname=Verdana,label=\"" + "domain-member" + "\"];");
                                            }

                                            content.AppendLine("/*");
                                            content.AppendLine("* Descendents domainMember");
                                            content.AppendLine("*/");

                                            foreach (DomainMember domainMemberDescendent in GetAllDescendents(domainMember.Member, crs.DomainMembers))
                                            {
                                                string sourceRoleDomainMember2 = domainMemberDescendent.SourceRole;

                                                if (!domainMemberDescendent.Usable)
                                                {
                                                    content.AppendLine("\t\"" + domainMemberDescendent.Member + domainMember.EffectiveRole + "\" [style = filled, fillcolor = beige, label=\"" + domainMemberDescendent.Member.Name + "\"];");
                                                    content.AppendLine("\t\"" + domainMemberDescendent.Domain.Name + sourceRoleDomainMember2 + "\" -> \"" + domainMemberDescendent.Member.Name + domainMember.EffectiveRole + "\" [fontsize=8  fontname=Verdana," +
                                                                        "label=<" +
                                                                        "<table cellpadding=\"0\" cellborder=\"0\" cellspacing=\"0\" border=\"0\">" +
                                                                        "<tr>" +
                                                                        "<td><font color=\"#0000FF\">domain-member</font></td>" +
                                                                        "</tr>" +
                                                                        "<tr>" +
                                                                        "<td><font color=\"#FF0000\">usable=false</font></td>" +
                                                                        "</tr>" +
                                                                        "</table>" +
                                                                        ">];");
                                                }
                                                else
                                                {
                                                    content.AppendLine("\t\"" + domainMemberDescendent.Member.Name + domainMember.EffectiveRole + "\" [style = filled, fillcolor = beige, label=\"" + domainMemberDescendent.Member.Name + "\"];");
                                                    content.AppendLine("\t\"" + domainMemberDescendent.Domain.Name + sourceRoleDomainMember2 + "\" -> \"" + domainMemberDescendent.Member.Name + domainMember.EffectiveRole + "\" [fontsize=8 fontcolor = " + fontColor + " fontname=Verdana,label=\"" + "domain-member" + "\"];");
                                                }
                                            }

                                        }
                                    }
                                }
                            }
                        }
                    }
                }

                content.AppendLine("}");
                content.AppendLine("");
                k = k + 1;
            }

            content.AppendLine("}");

            pathToDotFile = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "\\Tapioca\\dimension" + "Graph.dot";
            File.WriteAllText(pathToDotFile, content.ToString());
        }


        private void DrawPrimaryItemsInherited(XbrlDocument xbrlDoc, string fontColor, StringBuilder content, Locator fromLocator)
        {
            foreach (Arc arc in fromLocator.OutArcs)
            {
                Locator from = GetLocator(arc, arc.FromId);
                Concept conceptFrom = xbrlDoc.Dts.GetConceptByID(from.HrefResourceId);

                Locator to = GetLocator(arc, arc.ToId);
                Concept conceptTo = xbrlDoc.Dts.GetConceptByID(to.HrefResourceId);

                content.AppendLine("\t\"" + conceptFrom.Name + conceptFrom.SchemaElement.QualifiedName.Namespace + "\" [style = filled, fillcolor = gray, label=\"" + conceptFrom.Name + "\"];");
                content.AppendLine("\t\"" + conceptTo.Name + conceptTo.SchemaElement.QualifiedName.Namespace + "\" [style = filled, fillcolor = gray, label=\"" + conceptTo.Name + "\"];");
                content.AppendLine("\t\"" + conceptFrom.Name + conceptFrom.SchemaElement.QualifiedName.Namespace + "\" -> \"" + conceptTo.Name + conceptTo.SchemaElement.QualifiedName.Namespace + "\" [fontsize=8 fontcolor=gray fontname=Verdana,label=\"domain-member\nhypercube Inherited\"];");

                DrawPrimaryItemsInherited(xbrlDoc, fontColor, content, to);
            }
        }


        protected Locator GetLocator(Arc arc, string label)
        {
            foreach (Locator locator in arc.ExtendedLinkParent.Locators)
            {
                if (label.Equals(locator.Label))
                {
                    return locator;
                }
            }

            return null;
        }


        static int k = 1;


        public static void CreateFormulaDotFile(string treeViewId, XbrlDocument xbrlDoc, ref string pathToDotFile)
        {
            if (File.Exists("formulaGraph.dot"))
            {
                File.Delete("formulaGraph.dot");
            }

            pathToDotFile = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "\\Tapioca\\" + "formulaGraph.dot";

            string fontColor = "cornflowerblue";
            

            StringBuilder content = new StringBuilder();

            content.AppendLine("digraph " + "Dimensional" + "Graph {");
            content.AppendLine("graph [fontsize=10 fontname=\"Verdana\" compound=true];");
            content.AppendLine("node [shape=ellipse fontsize=10 fontname=\"Verdana\"];");
            content.AppendLine("edge[color = blue];");
            content.AppendLine("concentrate = red;");

            CreateAssertionSet(treeViewId, xbrlDoc, fontColor, content);

            CreateValueAssertion(xbrlDoc.Dts.DtsFormula.ValueAssertions, treeViewId, xbrlDoc, fontColor, content);

            CreateExistenceAssertion(xbrlDoc.Dts.DtsFormula.ExistenceAssertions, false, treeViewId, xbrlDoc, fontColor, content);

            CreateConsistencyAssertion(xbrlDoc.Dts.DtsFormula.ConsistencyAssertions, treeViewId, xbrlDoc, fontColor, content);

            CreateFormula(xbrlDoc, fontColor, content);
                    
            content.AppendLine("}");

            File.WriteAllText(pathToDotFile, content.ToString());
        }


        private static void CreateAssertionSet(string treeViewId, XbrlDocument xbrlDoc, string fontColor, StringBuilder content)
        {
            foreach (AssertionSet assertionSet in xbrlDoc.Dts.DtsFormula.AssertionSets)
            {
                content.AppendLine("\t\"" + assertionSet.Label + "\" [shape=box, style = filled, fillcolor = aquamarine, label=\"AssertionSet\n" + assertionSet.Label + "\"];");

                foreach (ValueAssertion assertion in assertionSet.ValueAssertions)
                {
                    content.AppendLine("\t\"" + assertionSet.Label + "\" -> \"" + assertion.Id + "\" [fontsize=8 fontcolor = " + fontColor + " fontname=Verdana,label=\"" + "assertion-set" + "\"];");
                }

                CreateValueAssertion(assertionSet.ValueAssertions, treeViewId, xbrlDoc, fontColor, content);

                foreach (ExistenceAssertion assertion in assertionSet.ExistenceAssertions)
                {
                    content.AppendLine("\t\"" + assertionSet.Label + "\" -> \"" + assertion.Id + "\" [fontsize=8 fontcolor = " + fontColor + " fontname=Verdana,label=\"" + "assertion-set" + "\"];");
                }

                CreateExistenceAssertion(assertionSet.ExistenceAssertions, true, treeViewId, xbrlDoc, fontColor, content);

                foreach (ConsistencyAssertion assertion in assertionSet.ConsistencyAssertions)
                {
                    content.AppendLine("\t\"" + assertionSet.Label + "\" -> \"" + assertion.Id + "\" [fontsize=8 fontcolor = " + fontColor + " fontname=Verdana,label=\"" + "assertion-set" + "\"];");
                }

                CreateConsistencyAssertion(assertionSet.ConsistencyAssertions, treeViewId, xbrlDoc, fontColor, content);
            }
        }


        private static void CreateValueAssertion(List<ValueAssertion> valueAssertions, string assertionId, XbrlDocument xbrlDoc, string fontColor, StringBuilder content)
        {
            int k = 0;

            foreach (ValueAssertion assertion in valueAssertions)
            {
                k = k + 1;
                if ("valueAssertion " + (assertion.Id != null ? assertion.Id : assertion.Label) == assertionId)
                {                    
                    string role = assertion.Role;
                    content.AppendLine("subgraph cluster_" + k + " {");
                    content.AppendLine("\tlabel = \"" + assertionId + "\";");
                    k = k + 1;

                    content.AppendLine("\t\"" + assertionId + "\" [shape=box, style = filled, fillcolor = aquamarine, label=\"ValueAssertion\naspectModel=" + assertion.AspectModel + "  implicitFiltering=" + assertion.ImplicitFiltering + "\ntest=" + assertion.Test + "\"];");

                    DrawGroupFilters(fontColor, content, assertion);

                    foreach (FactVariable factVariable in assertion.FactVariables)
                    {
                        foreach (VariableSet variableSet in assertion.VariableSetArcs)
                        {
                            if (variableSet.To.Equals(factVariable.Label))
                            {
                                content.AppendLine("\t\"" + assertionId + factVariable.Label + "\" [shape=box, style = filled, fillcolor = white, label=\" factVariable:" + variableSet.Name + "\nBindAsSequence=" + factVariable.BindAsSequence + "\nfallbackValue=" + factVariable.FallbackValue + "\"];");
                                content.AppendLine("\t\"" + assertionId + "\" -> \"" + assertionId + factVariable.Label + "\" [fontsize=8 fontcolor = " + fontColor + " fontname=Verdana,label=\"" + "variable-set" + "\"];");

                                DrawFilters(fontColor, content, factVariable, assertionId);
                            }
                        }
                    }

                    foreach (GeneralVariable generalVariable in assertion.GeneralVariables)
                    {
                        string select = Regex.Replace(generalVariable.Select, @"\s+", " ");

                        string msg = "";

                        foreach (string chunk in Split(select, 50))
                        {
                            msg = msg + chunk + "\n";
                        }
                        //select = select.Substring(0, select.Length / 2) + "\n" + select.Substring(select.Length / 2);

                        content.AppendLine("\t\"" + assertionId + generalVariable.Label + "\" [shape=box, style = filled, fillcolor = bisque, label=\"generalVariable:" + generalVariable.Label + "\nBindAsSequence=" + generalVariable.BindAsSequence + "\nselect=" + msg + "\"];");
                        content.AppendLine("\t\"" + assertionId + "\" -> \"" + assertionId + generalVariable.Label + "\" [fontsize=8 fontcolor = " + fontColor + " fontname=Verdana,label=\"" + "variable-set" + "\"];");
                    }

                    foreach (Parameter parameter in assertion.Parameters)
                    {
                        content.AppendLine("\t\"" + assertionId + parameter.Label + "\" [shape=box, style = filled, fillcolor = bisque2, label=\"" + parameter.Label + "\"];");
                        content.AppendLine("\t\"" + assertionId + "\" -> \"" + assertionId + parameter.Label + "\" [fontsize=8 fontcolor = " + fontColor + " fontname=Verdana,label=\"" + "parameter" + "\"];");
                    }

                    if (assertion.Precondition != null)
                    {
                        content.AppendLine("\t\"" + assertionId + assertion.Precondition.Label + "\" [shape=box, style = filled, fillcolor = tomato, label=\"Precondition=" + assertion.Precondition.Test + "\"];");
                        content.AppendLine("\t\"" + assertionId + "\" -> \"" + assertionId + assertion.Precondition.Label + "\" [fontsize=8 fontcolor = " + fontColor + " fontname=Verdana,label=\"" + "variable-set-precondition" + "\"];");
                    }

                    if (assertion.MessageSatisfied != null)
                    {
                        content.AppendLine("\t\"" + assertion.MessageSatisfied.Label + assertionId + "\" [shape=box, style = filled, fillcolor = deepskyblue, label=\"Message Satisfied\n" + assertion.MessageSatisfied.Label + assertion.MessageSatisfied.Content + "\"];");
                        content.AppendLine("\t\"" + assertionId + "\" -> \"" + assertion.MessageSatisfied.Label + assertionId + "\" [fontsize=8 fontcolor = " + fontColor + " fontname=Verdana,label=\"" + "assertion-satisfied-message" + "\"];");
                    }

                    if (assertion.MessageUnsatisfied != null)
                    {
                        content.AppendLine("\t\"" + assertion.MessageUnsatisfied.Label + assertionId + "\" [shape=box, style = filled, fillcolor = firebrick1, label=\"Message Unsatisfied\n" + assertion.MessageUnsatisfied.Label + assertion.MessageUnsatisfied.Content + "\"];");
                        content.AppendLine("\t\"" + assertionId + "\" -> \"" + assertion.MessageUnsatisfied.Label + assertionId + "\" [fontsize=8 fontcolor = " + fontColor + " fontname=Verdana,label=\"" + "assertion-unsatisfied-message" + "\"];");
                    }

                    content.AppendLine("\t}");
                    content.AppendLine("");
                }
            }
        }


        private static void CreateExistenceAssertion(List<ExistenceAssertion> existenceAssertions, bool isAssertionSet, string assertionId, XbrlDocument xbrlDoc, string fontColor, StringBuilder content)
        {
            foreach (ExistenceAssertion assertion in existenceAssertions)
            {
                if (isAssertionSet || "existenceAssertion " + (assertion.Id != null ? assertion.Id : assertion.Label) == assertionId)
                {
                    string role = assertion.Role;
                    content.AppendLine("subgraph cluster_" + k + " {");
                    content.AppendLine("\tlabel = \"" + assertionId + "\";");
                    k = k + 1;

                    content.AppendLine("\t\"" + assertionId + "\" [shape=box, style = filled, fillcolor = aquamarine, label=\"ExistenceAssertion\naspectModel=" + assertion.AspectModel + "  implicitFiltering=" + assertion.ImplicitFiltering + "\ntest=" + assertion.Test + "\"];");

                    DrawGroupFilters(fontColor, content, assertion);

                    foreach (FactVariable factVariable in assertion.FactVariables)
                    {
                        foreach (VariableSet variableSet in assertion.VariableSetArcs)
                        {
                            if (variableSet.To.Equals(factVariable.Label))
                            {
                                content.AppendLine("\t\"" + assertionId + factVariable.Label + "\" [shape=box, style = filled, fillcolor = white, label=\" factVariable:" + variableSet.Name + "\nBindAsSequence=" + factVariable.BindAsSequence + "\nfallbackValue=" + factVariable.FallbackValue + "\"];");
                                content.AppendLine("\t\"" + assertionId + "\" -> \"" + assertionId + factVariable.Label + "\" [fontsize=8 fontcolor = " + fontColor + " fontname=Verdana,label=\"" + "variable-set" + "\"];");

                                DrawFilters(fontColor, content, factVariable, assertionId);
                            }
                        }
                    }

                    foreach (GeneralVariable generalVariable in assertion.GeneralVariables)
                    {
                        string select = Regex.Replace(generalVariable.Select, @"\s+", " ");
                        if (select.Length > 100)
                        {
                            select = select.Substring(0, select.Length / 2) + "\n" + select.Substring(select.Length / 2);
                        }
                        content.AppendLine("\t\"" + assertionId + generalVariable.Label + "\" [shape=box, style = filled, fillcolor = bisque, label=\"generalVariable:" + generalVariable.Label + "\nBindAsSequence=" + generalVariable.BindAsSequence + "\nselect=" + select + "\"];");
                        content.AppendLine("\t\"" + assertionId + "\" -> \"" + assertionId + generalVariable.Label + "\" [fontsize=8 fontcolor = " + fontColor + " fontname=Verdana,label=\"" + "variable-set" + "\"];");
                    }

                    foreach (Parameter parameter in assertion.Parameters)
                    {
                        content.AppendLine("\t\"" + assertionId + parameter.Label + "\" [shape=box, style = filled, fillcolor = bisque2, label=\"" + parameter.Label + "\"];");
                        content.AppendLine("\t\"" + assertionId + "\" -> \"" + assertionId + parameter.Label + "\" [fontsize=8 fontcolor = " + fontColor + " fontname=Verdana,label=\"" + "parameter" + "\"];");
                    }

                    if (assertion.Precondition != null)
                    {
                        content.AppendLine("\t\"" + assertionId + assertion.Precondition.Label + "\" [shape=box, style = filled, fillcolor = tomato, label=\"Precondition=" + assertion.Precondition.Test + "\"];");
                        content.AppendLine("\t\"" + assertionId + "\" -> \"" + assertionId + assertion.Precondition.Label + "\" [fontsize=8 fontcolor = " + fontColor + " fontname=Verdana,label=\"" + "variable-set-precondition" + "\"];");
                    }

                    if (assertion.MessageSatisfied != null)
                    {
                        content.AppendLine("\t\"" + assertion.MessageSatisfied.Label + assertionId + "\" [shape=box, style = filled, fillcolor = deepskyblue, label=\"Message Satisfied\n" + assertion.MessageSatisfied.Label + assertion.MessageSatisfied.Content + "\"];");
                        content.AppendLine("\t\"" + assertionId + "\" -> \"" + assertion.MessageSatisfied.Label + assertionId + "\" [fontsize=8 fontcolor = " + fontColor + " fontname=Verdana,label=\"" + "assertion-satisfied-message" + "\"];");
                    }

                    if (assertion.MessageUnsatisfied != null)
                    {
                        content.AppendLine("\t\"" + assertion.MessageUnsatisfied.Label + assertionId + "\" [shape=box, style = filled, fillcolor = firebrick1, label=\"Message Unsatisfied\n" + assertion.MessageUnsatisfied.Label + assertion.MessageUnsatisfied.Content + "\"];");
                        content.AppendLine("\t\"" + assertionId + "\" -> \"" + assertion.MessageUnsatisfied.Label + assertionId + "\" [fontsize=8 fontcolor = " + fontColor + " fontname=Verdana,label=\"" + "assertion-unsatisfied-message" + "\"];");
                    }

                    content.AppendLine("\t}");
                    content.AppendLine("");
                }
            }
        }


        private static void CreateConsistencyAssertion(List<ConsistencyAssertion> consistencyAssertions, string assertionId, XbrlDocument xbrlDoc, string fontColor, StringBuilder content)
        {
            foreach (ConsistencyAssertion assertion in consistencyAssertions)
            {
                if ("consistencyAssertion " + (assertion.Id != null ? assertion.Id : assertion.Label) == assertionId)
                {
                    string role = assertion.Role;
                    content.AppendLine("subgraph cluster_" + k + " {");
                    content.AppendLine("\tlabel = \"" + assertionId + "\";");
                    k = k + 1;

                    content.AppendLine("\t\"" + assertionId + "\" [shape=box, style = filled, fillcolor = aquamarine, label=\"ConsistencyAssertion: " + assertionId +
                        "\nproportionalAcceptanceRadius=" + assertion.ProportionalAcceptanceRadius + "\nabsoluteAcceptanceRadius=" + assertion.AbsoluteAcceptanceRadius + "\nstrict=" + assertion.Strict + "\"];");

                    foreach (FormulaXBRL formula in assertion.FormulasXbrl)
                    {
                        content.AppendLine("\t\"" + formula.Label + assertionId + "\" [shape=box, style = filled, fillcolor = plum, label=\"Formula: " + formula.Label + "\naspectModel=" + formula.AspectModel + "  implicitFiltering=" + formula.ImplicitFiltering + "\n" + "  value=" + formula.Value + "  source=" + formula.Source + "\"];");
                        content.AppendLine("\t\"" + assertionId + "\" -> \"" + formula.Label + assertionId + "\" [fontsize=8 fontcolor = " + fontColor + " fontname=Verdana,label=\"" + "consistency-assertion-formula" + "\"];");

                        DrawGroupFilters(fontColor, content, formula);

                        foreach (FactVariable factVariable in formula.FactVariables)
                        {
                            foreach (VariableSet variableSet in formula.VariableSetArcs)
                            {
                                if (variableSet.To.Equals(factVariable.Label))
                                {
                                    content.AppendLine("\t\"" + formula.Label + factVariable.Label + "\" [shape=box, style = filled, fillcolor = white, label=\"factVariable:" + variableSet.Name + "\nBindAsSequence=" + factVariable.BindAsSequence + "\"];");
                                    content.AppendLine("\t\"" + formula.Label + assertionId + "\" -> \"" + formula.Label + factVariable.Label + "\" [fontsize=8 fontcolor = " + fontColor + " fontname=Verdana,label=\"" + "variable-set" + "\"];");

                                    DrawFilters(fontColor, content, factVariable, formula.Label);
                                }
                            }
                        }

                        foreach (GeneralVariable generalVariable in formula.GeneralVariables)
                        {
                            string select = Regex.Replace(generalVariable.Select, @"\s+", " ");
                            if (select.Length > 100)
                            {
                                select = select.Substring(0, select.Length / 2) + "\n" + select.Substring(select.Length / 2);
                            }
                            content.AppendLine("\t\"" + formula.Label + generalVariable.Label + "\" [shape=box, style = filled, fillcolor = bisque, label=\"generalVariable:" + generalVariable.Label + "\nBindAsSequence=" + generalVariable.BindAsSequence + "\nselect=" + select + "\"];");
                            content.AppendLine("\t\"" + formula.Label + assertionId + "\" -> \"" + formula.Label + generalVariable.Label + "\" [fontsize=8 fontcolor = " + fontColor + " fontname=Verdana,label=\"" + "variable-set" + "\"];");
                        }

                        foreach (Parameter parameter in formula.Parameters)
                        {
                            content.AppendLine("\t\"" + formula.Label + parameter.Label + "\" [shape=box, style = filled, fillcolor = bisque2, label=\"" + parameter.Label + "\"];");
                            content.AppendLine("\t\"" + formula.Label + assertionId + "\" -> \"" + formula.Label + parameter.Label + "\" [fontsize=8 fontcolor = " + fontColor + " fontname=Verdana,label=\"" + "parameter" + "\"];");
                        }

                        if (formula.Precondition != null)
                        {
                            content.AppendLine("\t\"" + formula.Label + formula.Precondition.Label + "\" [shape=box, style = filled, fillcolor = tomato, label=\"Precondition=" + formula.Precondition.Test + "\"];");
                            content.AppendLine("\t\"" + formula.Label + assertionId + "\" -> \"" + formula.Label + formula.Precondition.Label + "\" [fontsize=8 fontcolor = " + fontColor + " fontname=Verdana,label=\"" + "variable-set-precondition" + "\"];");
                        }
                    }

                    if (assertion.MessageSatisfied != null)
                    {
                        content.AppendLine("\t\"" + assertion.MessageSatisfied.Label + assertionId + "\" [shape=box, style = filled, fillcolor = deepskyblue, label=\"Message Satisfied\n" + assertion.MessageSatisfied.Label + assertion.MessageSatisfied.Content + "\"];");
                        content.AppendLine("\t\"" + assertionId + "\" -> \"" + assertion.MessageSatisfied.Label + assertionId + "\" [fontsize=8 fontcolor = " + fontColor + " fontname=Verdana,label=\"" + "assertion-satisfied-message" + "\"];");
                    }

                    if (assertion.MessageUnsatisfied != null)
                    {
                        content.AppendLine("\t\"" + assertion.MessageUnsatisfied.Label + assertionId + "\" [shape=box, style = filled, fillcolor = firebrick1, label=\"Message Unsatisfied\n" + assertion.MessageUnsatisfied.Label + assertion.MessageUnsatisfied.Content + "\"];");
                        content.AppendLine("\t\"" + assertionId + "\" -> \"" + assertion.MessageUnsatisfied.Label + assertionId + "\" [fontsize=8 fontcolor = " + fontColor + " fontname=Verdana,label=\"" + "assertion-unsatisfied-message" + "\"];");
                    }

                    content.AppendLine("\t}");
                    content.AppendLine("");
                }
            }
        }


        private static void CreateFormula(XbrlDocument xbrlDoc, string fontColor, StringBuilder content)
        {
            foreach (FormulaXBRL formula in xbrlDoc.Dts.DtsFormula.Formulas)
            {
                content.AppendLine("\t\"" + formula.Label + "\" [shape=box, style = filled, fillcolor = plum, label=\"Formula: " + formula.Label + "\naspectModel=" + formula.AspectModel + "  implicitFiltering=" + formula.ImplicitFiltering + "\n" + "  value=" + formula.Value + "  source=" + formula.Source + "\"];");

                DrawGroupFilters(fontColor, content, formula);

                foreach (FactVariable factVariable in formula.FactVariables)
                {
                    foreach (VariableSet variableSet in formula.VariableSetArcs)
                    {
                        if (variableSet.To.Equals(factVariable.Label))
                        {
                            content.AppendLine("\t\"" + formula.Label + factVariable.Label + "\" [shape=box, style = filled, fillcolor = white, label=\"factVariable:" + variableSet.Name + "\nBindAsSequence=" + factVariable.BindAsSequence + "\"];");
                            content.AppendLine("\t\"" + formula.Label + "\" -> \"" + formula.Label + factVariable.Label + "\" [fontsize=8 fontcolor = " + fontColor + " fontname=Verdana,label=\"" + "variable-set" + "\"];");

                            DrawFilters(fontColor, content, factVariable, formula.Label);
                        }
                    }
                }

                foreach (GeneralVariable generalVariable in formula.GeneralVariables)
                {
                    string select = Regex.Replace(generalVariable.Select, @"\s+", " ");
                    if (select.Length > 100)
                    {
                        select = select.Substring(0, select.Length / 2) + "\n" + select.Substring(select.Length / 2);
                    }
                    content.AppendLine("\t\"" + formula.Label + generalVariable.Label + "\" [shape=box, style = filled, fillcolor = bisque, label=\"generalVariable:" + generalVariable.Label + "\nBindAsSequence=" + generalVariable.BindAsSequence + "\nselect=" + select + "\"];");
                    content.AppendLine("\t\"" + formula.Label + "\" -> \"" + formula.Label + generalVariable.Label + "\" [fontsize=8 fontcolor = " + fontColor + " fontname=Verdana,label=\"" + "variable-set" + "\"];");
                }

                foreach (Parameter parameter in formula.Parameters)
                {
                    foreach (VariableSet variableSet in formula.VariableSetArcs)
                    {
                        if (variableSet.To.Equals(parameter.Label))
                        {
                            content.AppendLine("\t\"" + formula.Label + parameter.Label + "\" [shape=box, style = filled, fillcolor = bisque2, label=\"" + variableSet.Name + "\"];");
                            content.AppendLine("\t\"" + formula.Label + "\" -> \"" + formula.Label + parameter.Label + "\" [fontsize=8 fontcolor = " + fontColor + " fontname=Verdana,label=\"" + "parameter" + "\"];");
                        }
                    }
                }

                if (formula.Precondition != null)
                {
                    content.AppendLine("\t\"" + formula.Label + formula.Precondition.Label + "\" [shape=box, style = filled, fillcolor = tomato, label=\"Precondition=" + formula.Precondition.Test + "\"];");
                    content.AppendLine("\t\"" + formula.Label + "\" -> \"" + formula.Label + formula.Precondition.Label + "\" [fontsize=8 fontcolor = " + fontColor + " fontname=Verdana,label=\"" + "variable-set-precondition" + "\"];");
                }
            }
        }


        private static void DrawGroupFilters(string fontColor, StringBuilder content, VariableSet formula)
        {
            foreach (Filter filter in formula.GroupFilters)
            {
                if (filter.ResourceName.Equals("general"))
                {
                    GeneralFilter gf = filter as GeneralFilter;
                    content.AppendLine("\t\"" + filter.ResourceName + formula.Label + "\" [shape=box, style = filled, fillcolor = white, label=\"Filter\n" + filter.ResourceName + "\ntest=" + gf.Test + "\"];");
                    content.AppendLine("\t\"" + formula.Label + "\" -> \"" + filter.ResourceName + formula.Label + "\" [fontsize=8 fontcolor = " + fontColor + " fontname=Verdana,label=\"" + "variable-filter\ncomplement=" + filter.Complement + "\"];");
                }
                else
                {
                    content.AppendLine("\t\"" + filter.ResourceName + formula.Label + "\" [shape=box, style = filled, fillcolor = white, label=\"Filter\n" + filter.ResourceName + "\"];");
                    content.AppendLine("\t\"" + formula.Label + "\" -> \"" + filter.ResourceName + formula.Label + "\" [fontsize=8 fontcolor = " + fontColor + " fontname=Verdana,label=\"" + "variable-filter\ncomplement=" + filter.Complement + "\"];");
                }
            }
        }


        private static void DrawFilters(string fontColor, StringBuilder content, FactVariable factVariable, string assertionId)
        {
            foreach (Filter filter in factVariable.Filters)
            {
                if (filter.ResourceName.Equals("conceptName"))
                {
                    content.AppendLine("\t\"" + assertionId + factVariable.Label + filter.ResourceName + filter.Label + "\" [shape=box, style = filled, fillcolor = white, label=\"Filter\n" + filter.ResourceName + "\nlabel:" + filter.Label + "\"];");
                    content.AppendLine("\t\"" + assertionId + factVariable.Label + "\" -> \"" + assertionId + factVariable.Label + filter.ResourceName + filter.Label + "\" [fontsize=8 fontcolor = " + fontColor + " fontname=Verdana,label=\"" + "variable-filter\ncomplement=" + filter.Complement + "\ncover=" + filter.Cover + "\"];");

                    foreach (string conceptName in (filter as ConceptNameFilter).ConceptNameValues)
                    {
                        content.AppendLine("\t\"" + assertionId + conceptName + "\" [shape=box, style = filled, fillcolor = white, label=\"" + conceptName + "\"];");
                        content.AppendLine("\t\"" + assertionId + factVariable.Label + filter.ResourceName + filter.Label + "\" -> \"" + assertionId + conceptName + "\" [fontsize=8 fontcolor = " + fontColor + " fontname=Verdana,label=\"" + "concepName" + "\"];");
                    }
                }
                else if (filter.ResourceName.Equals("explicitDimension"))
                {
                    ExplicitDimensionFilter filterExplicitDim = filter as ExplicitDimensionFilter;
                    string dimension = filterExplicitDim.Dimension;

                    content.AppendLine("\t\"" + filter.Label + factVariable.Label + dimension + "\" [shape=box, style = filled, fillcolor = white, label=\"" + filter.ResourceName + "\nFilter:" + filter.Label + "\n" + dimension + "\"];");
                    content.AppendLine("\t\"" + assertionId + factVariable.Label + "\" -> \"" + filter.Label + factVariable.Label + dimension + "\" [fontsize=8 fontcolor = " + fontColor + " fontname=Verdana,label=\"" + "variable-filter\ncomplement=" + filter.Complement + "\ncover=" + filter.Cover + "\"];");

                    foreach (MemberModel memberModel in filterExplicitDim.MembersModel)
                    {
                        string msg = "";

                        if (memberModel.Linkrole != null && memberModel.Arcrole != null && memberModel.Axis != null)
                        {
                            msg = "Linkrole=" + memberModel.Linkrole + "\nArcrole=" + memberModel.Arcrole + "\nAxis=" + memberModel.Axis;
                        }

                        if (!string.IsNullOrEmpty(memberModel.QName))
                        {
                            content.AppendLine("\t\"" + memberModel.QName + filter.Label + dimension + "\" [shape=box, style = filled, fillcolor = white, label=\"Member\n" + memberModel.QName + "\n" + msg + "\"];");
                            content.AppendLine("\t\"" + filter.Label + factVariable.Label + dimension + "\" -> \"" + memberModel.QName + filter.Label + dimension + "\" [fontsize=8 fontcolor = " + fontColor + " fontname=Verdana,label=\"" + "Member\"];");
                        }

                        if (!string.IsNullOrEmpty(memberModel.QnameExpression))
                        {
                            content.AppendLine("\t\"" + memberModel.QnameExpression + filter.Label + dimension + "\" [shape=box, style = filled, fillcolor = white, label=\"Member\nexpression=" + memberModel.QnameExpression + "\n" + msg + "\"];");
                            content.AppendLine("\t\"" + filter.Label + factVariable.Label + dimension + "\" -> \"" + memberModel.QnameExpression + filter.Label + dimension + "\" [fontsize=8 fontcolor = " + fontColor + " fontname=Verdana,label=\"" + "Member\"];");
                        }

                        if (!string.IsNullOrEmpty(memberModel.Variable))
                        {
                            content.AppendLine("\t\"" + memberModel.Variable + filter.Label + dimension + "\" [shape=box, style = filled, fillcolor = white, label=\"Member\nvariable=" + memberModel.Variable + "\n" + msg + "\"];");
                            content.AppendLine("\t\"" + filter.Label + factVariable.Label + dimension + "\" -> \"" + memberModel.Variable + filter.Label + dimension + "\" [fontsize=8 fontcolor = " + fontColor + " fontname=Verdana,label=\"" + "Member\"];");
                        }                        
                    }

                }
                else if (filter.ResourceName.Equals("typedDimension"))
                {
                    TypedDimensionFilter filterTypedDim = filter as TypedDimensionFilter;
                    string dimension = filterTypedDim.Dimension;

                    string msg = "";

                    if (filterTypedDim.Test != null)
                    {
                        foreach (string chunk in Split(filterTypedDim.Test, 50))
                        {
                            msg = msg + chunk + "\n";
                        }
                    }

                    content.AppendLine("\t\"" + filter.ResourceName + factVariable.Label + dimension + "\" [shape=box, style = filled, fillcolor = white, label=\"" + filter.ResourceName + "\ndimension=" + dimension + "\ntest=" + msg + "\"];");
                    content.AppendLine("\t\"" + assertionId + factVariable.Label + "\" -> \"" + filter.ResourceName + factVariable.Label + dimension + "\" [fontsize=8 fontcolor = " + fontColor + " fontname=Verdana,label=\"" + "variable-filter\ncomplement=" + filter.Complement + "\ncover=" + filter.Cover + "\"];");

                }
                else if (filter.ResourceName.Equals("andFilter"))
                {
                    content.AppendLine("\t\"" + filter.ResourceName + factVariable.Label + "\" [shape=box, style = filled, fillcolor = white, label=\"Filter\n" + filter.ResourceName + "\"];");
                    content.AppendLine("\t\"" + assertionId + factVariable.Label + "\" -> \"" + filter.ResourceName + factVariable.Label + "\" [fontsize=8 fontcolor = " + fontColor + " fontname=Verdana,label=\"" + "variable-filter\ncomplement=" + filter.Complement + "\ncover=" + filter.Cover + "\"];");

                    DrawSubFilters(fontColor, content, factVariable.Label, filter as BooleanFilter);
                }
                else if (filter.ResourceName.Equals("orFilter"))
                {
                    content.AppendLine("\t\"" + filter.ResourceName + factVariable.Label + "\" [shape=box, style = filled, fillcolor = white, label=\"Filter\n" + filter.ResourceName + "\"];");
                    content.AppendLine("\t\"" + assertionId + factVariable.Label + "\" -> \"" + filter.ResourceName + factVariable.Label + "\" [fontsize=8 fontcolor = " + fontColor + " fontname=Verdana,label=\"" + "variable-filter\ncomplement=" + filter.Complement + "\ncover=" + filter.Cover + "\"];");

                    DrawSubFilters(fontColor, content, factVariable.Label, filter as BooleanFilter);                    
                }
                else if (filter.ResourceName.Equals("general"))
                {
                    GeneralFilter gf = filter as GeneralFilter;

                    string msg = "";

                    if (gf.Test != null)
                    {
                        foreach (string chunk in Split(gf.Test, 50))
                        {
                            msg = msg + chunk + "\n";
                        }
                    }

                    content.AppendLine("\t\"" + factVariable.Label + filter.ResourceName + filter.Label + "\" [shape=box, style = filled, fillcolor = white, label=\"Filter\n" + filter.ResourceName + "\ntest=" + msg + "\"];");
                    content.AppendLine("\t\"" + assertionId + factVariable.Label + "\" -> \"" + factVariable.Label + filter.ResourceName + filter.Label + "\" [fontsize=8 fontcolor = " + fontColor + " fontname=Verdana,label=\"" + "variable-filter\ncomplement=" + filter.Complement + "\ncover=" + filter.Cover + "\"];");
                }
                else if (filter.ResourceName.StartsWith("match"))
                {
                    MatchFilter mf = filter as MatchFilter;
                    content.AppendLine("\t\"" + filter.ResourceName + factVariable.Label + mf.Variable + "\" [shape=box, style = filled, fillcolor = white, label=\"Filter\n" + filter.ResourceName + "\nvariable=" + mf.Variable + "\"];");
                    content.AppendLine("\t\"" + assertionId + factVariable.Label + "\" -> \"" + filter.ResourceName + factVariable.Label + mf.Variable + "\" [fontsize=8 fontcolor = " + fontColor + " fontname=Verdana,label=\"" + "variable-filter\ncomplement=" + filter.Complement + "\ncover=" + filter.Cover + "\"];");
                }
                else if (filter.ResourceName.Equals("relativeFilter"))
                {
                    RelativeFilter rf = filter as RelativeFilter;
                    content.AppendLine("\t\"" + filter.ResourceName + factVariable.Label + rf.Variable + "\" [shape=box, style = filled, fillcolor = white, label=\"Filter\n" + filter.ResourceName + "\nvariable=" + rf.Variable + "\"];");
                    content.AppendLine("\t\"" + assertionId + factVariable.Label + "\" -> \"" + filter.ResourceName + factVariable.Label + rf.Variable + "\" [fontsize=8 fontcolor = " + fontColor + " fontname=Verdana,label=\"" + "variable-filter\ncomplement=" + filter.Complement + "\ncover=" + filter.Cover + "\"];");
                }
                else if (filter.ResourceName.Equals("aspectCover"))
                {
                    content.AppendLine("\t\"" + factVariable.Label + filter.ResourceName + filter.Label + "\" [shape=box, style = filled, fillcolor = white, label=\"Filter\n" + filter.ResourceName + "\nlabel:" + filter.Label + "\"];");
                    content.AppendLine("\t\"" + assertionId + factVariable.Label + "\" -> \"" + factVariable.Label + filter.ResourceName + filter.Label + "\" [fontsize=8 fontcolor = " + fontColor + " fontname=Verdana,label=\"" + "variable-filter\ncomplement=" + filter.Complement + "\ncover=" + filter.Cover + "\"];");

                    AspectCoverFilter acf = filter as AspectCoverFilter;

                    foreach (string aspect in acf.Aspects)
                    {
                        content.AppendLine("\t\"" + aspect + filter.Label + "\" [shape=box, style = filled, fillcolor = white, label=\"Aspect:\n" + aspect + "\"];");
                        content.AppendLine("\t\"" + factVariable.Label + filter.ResourceName + filter.Label + "\" -> \"" + aspect + filter.Label + "\" [fontsize=8 fontcolor = " + fontColor + " fontname=Verdana,label=\"" + "aspect cover" + "\"];");
                    }

                    if (acf.Dimension != null)
                    {
                        content.AppendLine("\t\"" + acf.Dimension + filter.Label + "\" [shape=box, style = filled, fillcolor = white, label=\"Aspect:\n" + acf.Dimension + "\"];");
                        content.AppendLine("\t\"" + factVariable.Label + filter.ResourceName + filter.Label + "\" -> \"" + acf.Dimension + filter.Label + "\" [fontsize=8 fontcolor = " + fontColor + " fontname=Verdana,label=\"" + "aspect cover" + "\"];");
                    }

                    if (acf.ExcludeDimension != null)
                    {
                        content.AppendLine("\t\"" + acf.ExcludeDimension + filter.Label + "\" [shape=box, style = filled, fillcolor = white, label=\"Aspect:\n" + acf.ExcludeDimension + "\"];");
                        content.AppendLine("\t\"" + factVariable.Label + filter.ResourceName + filter.Label + "\" -> \"" + acf.ExcludeDimension + filter.Label + "\" [fontsize=8 fontcolor = " + fontColor + " fontname=Verdana,label=\"" + "aspect cover" + "\"];");
                    }
                }
                else if (filter.ResourceName.Equals("conceptRelation"))
                {
                    ConceptRelationFilter crf = filter as ConceptRelationFilter;
                    content.AppendLine("\t\"" + factVariable.Label + filter.ResourceName + filter.Label + "\" [shape=box, style = filled, fillcolor = white, label=\"Filter\n" + filter.ResourceName +
                        "\nsource=" + crf.Source + "\nlinkrole=" + crf.Linkrole + "\narcrole=" + crf.Arcrole + "\naxis=" + crf.Axis + "\ngenerations=" + crf.Generations + "\"];");
                    content.AppendLine("\t\"" + assertionId + factVariable.Label + "\" -> \"" + factVariable.Label + filter.ResourceName + filter.Label + "\" [fontsize=8 fontcolor = " + fontColor + " fontname=Verdana,label=\"" + "variable-filter\ncomplement=" + filter.Complement + "\ncover=" + filter.Cover + "\"];");
                }
                else if (filter.ResourceName.Equals("conceptDataType"))
                {
                    ConceptDataTypeFilter cdtf = filter as ConceptDataTypeFilter;
                    content.AppendLine("\t\"" + factVariable.Label + filter.ResourceName + filter.Label + "\" [shape=box, style = filled, fillcolor = white, label=\"Filter\n" + filter.ResourceName + "\nDataType=" + cdtf.QName + "\"];");
                    content.AppendLine("\t\"" + assertionId + factVariable.Label + "\" -> \"" + factVariable.Label + filter.ResourceName + filter.Label + "\" [fontsize=8 fontcolor = " + fontColor + " fontname=Verdana,label=\"" + "variable-filter\ncomplement=" + filter.Complement + "\ncover=" + filter.Cover + "\"];");
                }
                else if (filter.ResourceName.Equals("parentFilter"))
                {
                    ParentFilter pf = filter as ParentFilter;

                    content.AppendLine("\t\"" + factVariable.Label + filter.ResourceName + filter.Label + "\" [shape=box, style = filled, fillcolor = white, label=\"Filter\n" + filter.ResourceName + "\nlabel:" + filter.Label + "\"];");
                    content.AppendLine("\t\"" + assertionId + factVariable.Label + "\" -> \"" + factVariable.Label + filter.ResourceName + filter.Label + "\" [fontsize=8 fontcolor = " + fontColor + " fontname=Verdana,label=\"" + "variable-filter\ncomplement=" + filter.Complement + "\ncover=" + filter.Cover + "\"];");

                    content.AppendLine("\t\"" + filter.ResourceName + filter.Label + pf.Parent + "\" [shape=box, style = filled, fillcolor = white, label=\"" + pf.Parent + "\"];");
                    content.AppendLine("\t\"" + factVariable.Label + filter.ResourceName + filter.Label + "\" -> \"" + filter.ResourceName + filter.Label + pf.Parent + "\" [fontsize=8 fontcolor = " + fontColor + " fontname=Verdana,label=\"" + "parent" + "\"];");
                }
                else if (filter.ResourceName.Equals("instantDuration"))
                {
                    InstantDurationFilter idf = filter as InstantDurationFilter;
                    content.AppendLine("\t\"" + factVariable.Label + filter.ResourceName + filter.Label + "\" [shape=box, style = filled, fillcolor = white, label=\"Filter\n" + filter.ResourceName + "\nlabel:" + filter.Label + "\nboundary=" + idf.Boundary + "\nvariable=" + idf.Variable + "\"];");
                    content.AppendLine("\t\"" + assertionId + factVariable.Label + "\" -> \"" + factVariable.Label + filter.ResourceName + filter.Label + "\" [fontsize=8 fontcolor = " + fontColor + " fontname=Verdana,label=\"" + "variable-filter\ncomplement=" + filter.Complement + "\ncover=" + filter.Cover + "\"];");
                }
                else
                {
                    content.AppendLine("\t\"" + factVariable.Label + filter.ResourceName + filter.Label + "\" [shape=box, style = filled, fillcolor = white, label=\"Filter\n" + filter.ResourceName + "\nlabel:" + filter.Label + "\"];");
                    content.AppendLine("\t\"" + assertionId + factVariable.Label + "\" -> \"" + factVariable.Label + filter.ResourceName + filter.Label + "\" [fontsize=8 fontcolor = " + fontColor + " fontname=Verdana,label=\"" + "variable-filter\ncomplement=" + filter.Complement + "\ncover=" + filter.Cover + "\"];");
                }
            }
        }


        private static void DrawSubFilters(string fontColor, StringBuilder content, string label, BooleanFilter booleanFilter)
        {
            foreach (Filter subFilter in booleanFilter.SubFilters)
            {
                if (subFilter.ResourceName.Equals("conceptName"))
                {
                    foreach (string conceptName in (subFilter as ConceptNameFilter).ConceptNameValues)
                    {
                        content.AppendLine("\t\"" + conceptName + "\" [shape=box, style = filled, fillcolor = white, label=\"" + conceptName + "\"];");
                        content.AppendLine("\t\"" + booleanFilter.ResourceName + label + "\" -> \"" + conceptName + "\" [fontsize=8 fontcolor = " + fontColor + " fontname=Verdana,label=\"" + "concepName" + "\"];");
                    }
                }
                else if (subFilter.ResourceName.Equals("andFilter"))
                {
                    content.AppendLine("\t\"" + subFilter.ResourceName + booleanFilter.ResourceName + "\" [shape=box, style = filled, fillcolor = white, label=\"Filter\n" + subFilter.ResourceName + "\"];");
                    content.AppendLine("\t\"" + booleanFilter.ResourceName + label + "\" -> \"" + subFilter.ResourceName + booleanFilter.ResourceName + "\" [fontsize=8 fontcolor = " + fontColor + " fontname=Verdana,label=\"" + "variable-filter\ncomplement=" + booleanFilter.Complement + "\ncover=" + booleanFilter.Cover + "\"];");

                    DrawSubFilters(fontColor, content, booleanFilter.ResourceName, subFilter as BooleanFilter);
                }
                else if (subFilter.ResourceName.Equals("orFilter"))
                {
                    content.AppendLine("\t\"" + subFilter.ResourceName + booleanFilter.ResourceName + "\" [shape=box, style = filled, fillcolor = white, label=\"Filter\n" + subFilter.ResourceName + "\"];");
                    content.AppendLine("\t\"" + booleanFilter.ResourceName + label + "\" -> \"" + subFilter.ResourceName + booleanFilter.ResourceName + "\" [fontsize=8 fontcolor = " + fontColor + " fontname=Verdana,label=\"" + "variable-filter\ncomplement=" + booleanFilter.Complement + "\ncover=" + booleanFilter.Cover + "\"];");

                    DrawSubFilters(fontColor, content, booleanFilter.ResourceName, subFilter as BooleanFilter);
                }
                else
                {
                    content.AppendLine("\t\"" + subFilter.ResourceName + booleanFilter.ResourceName + "\" [shape=box, style = filled, fillcolor = white, label=\"Filter\n" + subFilter.ResourceName + "\"];");
                    content.AppendLine("\t\"" + booleanFilter.ResourceName + label + "\" -> \"" + subFilter.ResourceName + booleanFilter.ResourceName + "\" [fontsize=8 fontcolor = " + fontColor + " fontname=Verdana,label=\"" + "variable-filter\ncomplement=" + booleanFilter.Complement + "\ncover=" + booleanFilter.Cover + "\"];");
                }
            }
        }


        private static IEnumerable<string> Split(string str, int chunkSize)
        {
            for (int i = 0; i < str.Length; i += chunkSize)
            {
                yield return str.Substring(i, Math.Min(chunkSize, str.Length - i));
            }
        }




        public static void CreateDTSDotFile(XbrlDocument xbrlDocument)
        {
            xbrlDoc = xbrlDocument;

            StringBuilder content = new StringBuilder();

            content.AppendLine("strict digraph " + "DTS" + "Graph {");
            content.AppendLine("graph [fontsize=10 fontname=\"Verdana\" ];");
            content.AppendLine("node [shape=record fontsize=10 fontname=\"Verdana\"];");
            content.AppendLine("edge[color = blue];");
            //content.AppendLine("concentrate = red;");            

            content.AppendLine("subgraph cluster_1 {");
            content.AppendLine("\tlabel = \"Discoverable Taxonomy Set (DTS)\";");

            foreach (TaxonomySchema currentSchema in xbrlDoc.Dts.TaxonomySchemas)
            {
                if (xbrlDoc.DocType == "xbrl")
                {
                    if (currentSchema.ParentDocument != null && currentSchema.ParentDocument == xbrlDoc)
                    {
                        content.AppendLine("\t\"" + xbrlDoc.FileName + "\"" + " [shape=ellipse, style = filled, fillcolor = aquamarine, label=\"" + xbrlDoc.FileName + "\"];");
                        content.AppendLine("\t\"" + currentSchema.FileName + "\"" + " [shape=box, style = filled, fillcolor = white, label=\"" + currentSchema.FileName + "\"];");
                        content.AppendLine("\t\"" + xbrlDoc.FileName + "\" -> \"" + currentSchema.FileName + "\" [fontsize=8 fontcolor = grey55 fontname=Verdana,label=\"" + "schemaRef" + "\"];");

                        AddExternalSchema(content, currentSchema.XmlSchema, currentSchema.FileName);

                        foreach (LinkbaseDocument currentLinkbase in xbrlDoc.Dts.LinkbaseDocuments)
                        {
                            if (currentLinkbase.Schema != null && currentLinkbase.Schema == currentSchema.XmlSchema)
                            {
                                content.AppendLine("\t\"" + currentSchema.FileName + "\"" + " [shape=box, style = filled, fillcolor = white, label=\"" + currentSchema.FileName + "\"];");
                                content.AppendLine("\t\"" + currentLinkbase.FileName + "\"" + " [shape = hexagon, style = filled, fillcolor = forestgreen, label=\"" + currentLinkbase.FileName + "\"];");
                                content.AppendLine("\t\"" + currentSchema.FileName + "\" -> \"" + currentLinkbase.FileName + "\" [fontsize=8 fontcolor = grey55 fontname=Verdana,label=\"" + "linkbaseRef" + "\"];");

                                AddSchemaFromLinkbase(content, currentLinkbase, currentLinkbase.FileName);
                            }
                        }
                    }
                }
                else if (xbrlDoc.DocType == "schema")
                {
                    if (currentSchema.ParentDocument == xbrlDoc)
                    {
                        content.AppendLine("\t\"" + xbrlDoc.FileName + "\"" + " [shape=ellipse, style = filled, fillcolor = aquamarine, label=\"" + xbrlDoc.FileName + "\"];");
                        content.AppendLine("\t\"" + currentSchema.FileName + "\"" + " [shape=box, style = filled, fillcolor = white, label=\"" + currentSchema.FileName + "\"];");
                        content.AppendLine("\t\"" + xbrlDoc.FileName + "\" -> \"" + currentSchema.FileName + "\" [fontsize=8 fontcolor = grey55 fontname=Verdana,label=\"" + "schemaRef" + "\"];");
                    }

                    AddExternalSchema(content, currentSchema.XmlSchema, currentSchema.FileName);

                    foreach (LinkbaseDocument currentLinkbase in xbrlDoc.Dts.LinkbaseDocuments)
                    {
                        if (currentLinkbase.Schema != null && currentLinkbase.Schema == (xbrlDoc as TaxonomySchema).XmlSchema)
                        {
                            content.AppendLine("\t\"" + xbrlDoc.FileName + "\"" + " [shape=ellipse, style = filled, fillcolor = aquamarine, label=\"" + xbrlDoc.FileName + "\"];");
                            content.AppendLine("\t\"" + currentLinkbase.FileName + "\"" + " [shape = hexagon, style = filled, fillcolor = forestgreen, label=\"" + currentLinkbase.FileName + "\"];");
                            content.AppendLine("\t\"" + xbrlDoc.FileName + "\" -> \"" + currentLinkbase.FileName + "\" [fontsize=8 fontcolor = grey55 fontname=Verdana,label=\"" + "linkbaseRef" + "\"];");

                            AddSchemaFromLinkbase(content, currentLinkbase, currentLinkbase.FileName);
                        }
                    }
                }
                else
                {
                    if (currentSchema.ParentDocument == xbrlDoc)
                    {
                        content.AppendLine("\t\"" + xbrlDoc.FileName + "\"" + " [shape=ellipse, style = filled, fillcolor = aquamarine, label=\"" + xbrlDoc.FileName + "\"];");
                        content.AppendLine("\t\"" + currentSchema.FileName + "\"" + " [shape=box, style = filled, fillcolor = white, label=\"" + currentSchema.FileName + "\"];");
                        content.AppendLine("\t\"" + xbrlDoc.FileName + "\" -> \"" + currentSchema.FileName + "\" [fontsize=8 fontcolor = grey55 fontname=Verdana,label=\"" + "imports" + "\"];");
                    }

                    AddExternalSchema(content, currentSchema.XmlSchema, xbrlDoc.FileName);
                }
            }

            AddLinkbaseNode(content);

            content.AppendLine("\t}");
            content.AppendLine("}");

            File.WriteAllText(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "\\Tapioca\\DTSGraph.dot", content.ToString());
        }


        private static void AddLinkbaseNode(StringBuilder content)
        {
            foreach (LinkbaseDocument currentLinkbase in xbrlDoc.Dts.LinkbaseDocuments)
            {
                if (currentLinkbase.Instance != null && currentLinkbase.Instance == xbrlDoc)
                {
                    //content.AppendLine("\t\"" + xbrlDoc.FileName + "\"" + " [shape=ellipse, style = filled, fillcolor = aquamarine, label=\"" + xbrlDoc.FileName + "\"];");
                    content.AppendLine("\t\"" + currentLinkbase.FileName + "\"" + " [shape = hexagon, style = filled, fillcolor = forestgreen, label=\"" + currentLinkbase.FileName + "\"];");
                    content.AppendLine("\t\"" + xbrlDoc.FileName + "\" -> \"" + currentLinkbase.FileName + "\" [fontsize=8 fontcolor = grey55 fontname=Verdana,label=\"" + "linkbaseRef" + "\"];");

                    AddSchemaFromLinkbase(content, currentLinkbase, currentLinkbase.FileName);
                }
            }
        }


        private static void AddExternalSchema(StringBuilder content, XmlSchema currentSchema, string schemaName)
        {
            foreach (XmlSchemaObject schema in currentSchema.Includes)
            {
                XmlSchema externalSchema = null;

                if (schema is XmlSchemaImport)
                {
                    externalSchema = ((XmlSchemaImport)schema).Schema;

                    string schemaImportName = Path.GetFileName(externalSchema.SourceUri);

                    //content.AppendLine("\t\"" + schemaName + "\"" + " [shape=box, style = filled, fillcolor = white, label=\"" + schemaName + "\"];");
                    content.AppendLine("\t\"" + schemaImportName + "\"" + " [shape=box, style = filled, fillcolor = white, label=\"" + schemaImportName + "\"];");
                    content.AppendLine("\t\"" + schemaName + "\" -> \"" + schemaImportName + "\" [fontsize=8 fontcolor = grey55 fontname=Verdana,label=\"" + "imports" + "\"];");

                    AddExternalSchema(content, externalSchema, schemaImportName);

                    foreach (LinkbaseDocument currentLinkbase in xbrlDoc.Dts.LinkbaseDocuments)
                    {
                        if (currentLinkbase.Schema != null && currentLinkbase.Schema == externalSchema)
                        {
                            //content.AppendLine("\t\"" + schemaName + "\"" + " [shape=box, style = filled, fillcolor = white, label=\"" + schemaName + "\"];");
                            content.AppendLine("\t\"" + currentLinkbase.FileName + "\"" + " [shape = hexagon, style = filled, fillcolor = forestgreen, label=\"" + currentLinkbase.FileName + "\"];");
                            content.AppendLine("\t\"" + schemaName + "\" -> \"" + currentLinkbase.FileName + "\" [fontsize=8 fontcolor = grey55 fontname=Verdana,label=\"" + "linkbaseRef" + "\"];");

                            AddSchemaFromLinkbase(content, currentLinkbase, currentLinkbase.FileName);
                        }
                    }
                }
            }
        }


        private static void AddSchemaFromLinkbase(StringBuilder content, LinkbaseDocument currentLinkbase, string linkbaseName)
        {
            content.AppendLine("\t\"" + linkbaseName + "\" -> \"" + "xbrl-linkbase-2003-12-31.xsd" + "\" [fontsize=8 fontcolor = grey55 fontname=Verdana,label=\"" + "imports" + "\"];");
            content.AppendLine("\t\"" + "xbrl-linkbase-2003-12-31.xsd" + "\" -> \"" + "xl-2003-12-31.xsd" + "\" [fontsize=8 fontcolor = grey55 fontname=Verdana,label=\"" + "imports" + "\"];");
            content.AppendLine("\t\"" + "xbrl-linkbase-2003-12-31.xsd" + "\" -> \"" + "xlink-2003-12-31.xsd" + "\" [fontsize=8 fontcolor = grey55 fontname=Verdana,label=\"" + "imports" + "\"];");

            foreach (TaxonomySchema currentSchema in xbrlDoc.Dts.TaxonomySchemas)
            {
                if ((currentSchema.ParentDocument != null && currentSchema.ParentDocument == currentLinkbase) ||
                    currentSchema.FileName.Equals("xbrl-linkbase-2003-12-31.xsd"))
                {
                    //content.AppendLine("\t\"" + currentLinkbase.FileName + "\"" + " [shape=hexagon, style = filled, fillcolor = forestgreen, label=\"" + currentLinkbase.FileName + "\"];");
                    content.AppendLine("\t\"" + currentSchema.FileName + "\"" + " [shape=box, style = filled, fillcolor = white, label=\"" + currentSchema.FileName + "\"];");
                    content.AppendLine("\t\"" + linkbaseName + "\" -> \"" + currentSchema.FileName + "\" [fontsize=8 fontcolor = grey55 fontname=Verdana,label=\"" + "imports" + "\"];");

                    AddExternalSchema(content, currentSchema.XmlSchema, currentSchema.FileName);
                }
            }
        }


        private static List<DomainMember> GetAllDescendents(Concept member, List<DomainMember> domainMemberList)
        {
            List<DomainMember> domainMembers = new List<DomainMember>();

            foreach (DomainMember domainMember in domainMemberList)
            {
                if (domainMember.Domain.Id.Equals(member.Id))
                {
                    if (!domainMembers.Contains(domainMember))
                    {
                        domainMembers.Add(domainMember);
                        domainMembers.AddRange(GetAllDescendents(domainMember.Member, domainMemberList));
                    }
                }
            }

            return domainMembers;
        }

    }
}
